package pw_cryption

import (
	"errors"
	"fmt"
	"os"
	"path"
	"sasuke/config"
	"sasuke/utils"
)

type Silencer struct {
	PublicKeyFile string
	PrivateKeyFile string
}

func New() *Silencer {
	priv, pub := initKeyFiles()
	return &Silencer{PrivateKeyFile: priv,PublicKeyFile: pub}
}

func (s *Silencer) Encrypt(rawfile string) (string,error) {
	if !IsExist(rawfile){
		return rawfile,errors.New("文件不存在")
	}
	// 生成文件名
	lockfile:=rawfile+".locked"
	lockkey:=rawfile+".key"
	// 随机一个Aes的密钥
	aesKey := GetRandomString(32)
	// 加密Aes的Token
	pubKey,err := readPublicKey(s.PublicKeyFile) // 提取公匙
	if err!=nil{
		return "提取公钥错误",err
	}
	encryData,err := rsaPublicKeyEncrypt([]byte(aesKey),pubKey) // 加密密钥
	if err!=nil{
		return "加密密钥错误",err
	}
	utils.WriteFileByBytes(lockkey,encryData,os.ModePerm) // 生成密文密钥文件
	// 用Aes将文件加密
	ch,err:=utils.ReadByChan(rawfile,1024*1024)
	if err!=nil{
		return "读取源文件",err
	}
	ench, err := aes_encrypt(ch, aesKey)
	if err!=nil{
		return "加密文件错误",err
	}
	// 写文件
	err=utils.WriteByChan(ench, lockfile)
	return lockfile,err
}

func (s *Silencer) Decrypt(rawfile string) (string,error) {
	// 生成文件名
	lockfile:=rawfile+".locked"
	lockkey:=rawfile+".key"
	if !IsExist(lockfile){
		return lockfile,errors.New("文件不存在")
	}
	if !IsExist(lockkey){
		return lockkey,errors.New("文件不存在")
	}
	bs:=utils.ReadFile2Bytes(lockkey)
	priKey,err := readPrivateKey(s.PrivateKeyFile) // 解密私匙
	if err!=nil{
		return "解密私匙错误",err
	}
	decryData,err := rsaPrivateKeyDecrypt(bs,priKey) // 解密数据
	if err!=nil{
		return "解密数据错误",err
	}
	aesKey:=string(decryData)
	fmt.Println("明文密钥：",aesKey)
	// 读取文件
	endata, err := utils.ReadByChan(lockfile,1024*1024+16)
	if err!=nil{
		return "读取密文件错误",err
	}
	dech, err := aes_decrypt(endata, aesKey)
	if err!=nil{
		return "取密文件错误",err
	}
	// 写文件
	err=utils.WriteByChan(dech, rawfile)
	return rawfile,err
}



// 加密
func aes_encrypt(inChan <-chan []byte, key string) (<-chan []byte, error) {
	return crypt(inChan, key, AesEncryptECB)
}

// 解密
func aes_decrypt(inChan <-chan []byte, key string) (<-chan []byte, error) {
	return crypt(inChan, key, AesDecryptECB)
}
// 加解密
func crypt(inChan <-chan []byte, key string, f func([]byte, []byte) []byte) (<-chan []byte, error) {
	outCh := make(chan []byte)
	go func() {
		defer close(outCh)
		for p := range inChan {
			en := f(p, []byte(key))
			outCh <- en
		}
	}()
	return outCh, nil
}
func initKeyFiles()(string,string){
	dir:=config.UserHome()
	privkey_file:=path.Join(dir,"sasuke.pri.key")
	pubkey_file:=path.Join(dir,"sasuke.pub.key")
	if IsExist(privkey_file){
	}else{
		// 生成私匙和公匙
		pri,_ := os.Create(privkey_file)
		pub,_ := os.Create(pubkey_file)
		defer pri.Close()
		defer pub.Close()
		genKey(pri,pub,2048)
	}
	return privkey_file,pubkey_file
}

func IsExist(path string) bool {
	_, err := os.Stat(path)
	return err == nil || os.IsExist(err)
}